/*
 * ipassbook 0.6.0
 * Copyright (C)2009 wateray and contributors
 * wateray@gmail.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

package com.wateray.ipassbook.ui.dialog.wizard;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;

import com.wateray.ipassbook.domain.Entity;
import com.wateray.ipassbook.ui.widget.TitleMessageDialog;
import com.wateray.ipassbook.util.LanguageLoader;

/**
 * @author wateray
 * @create 2009-5-16
 */
public abstract class AbstractWizardDialog extends TitleMessageDialog implements IWizardDialog{


	 /**
	 * serialVersionUID.
	 */
	private static final long serialVersionUID = 1L;
	
	/**The back button.*/
	protected JButton backButton;
	
	/**The next button.*/
	protected JButton nextButton;
	
	/** page Count.*/
	protected int pageCount;
	protected JPanel currentPage;
	private int currentPageIndex;
	
	/** leftCenterPane.*/
	protected JPanel leftCenterPane;
	protected GridBagLayout leftCenterPaneGridbag;
	protected GridBagConstraints leftCenterPaneConstraints;
	private JLabel titleStepLabel;
	private Vector<JLabel> setpLabels;
	
	/**rightCenterPane.*/
	protected JPanel rightCenterPane;
	private CardLayout cardLayout;
	
	/** canFinish. finishButton enable or disable. default is false. */
	protected int canFinishPageCount = -1;
	
	private Entity entity;

	/**
	 * @param owner -- the owner of this wizard.
	 * @param width -- the width.
	 * @param height -- the height.
	 * @param modal -- the modal.
	 * @param title -- the title.
	 * */
	public AbstractWizardDialog(Component owner, int width, int height, boolean modal, String title) {
		 super(owner, width, height, modal, title);
		 
			this.putButton(getNextButton());
			this.putButton(getBackButton());
			this.layoutButtonPanel();
			
			//set finishButton disable.
			getFinishButton().setEnabled(false);
	 }
	
    public int getPageCount(){
    	return getRightCenterPane().getComponentCount();
    }
    
    protected void setCanFinishPageCount(int pageCount){
    	canFinishPageCount = pageCount;
    }
    @Override
    protected JComponent getCenterPane(){
    	if(centerPane == null){
    		centerPane = new JPanel(new BorderLayout());
    		centerPane.add(getLeftCenterPane(),BorderLayout.WEST);
    		centerPane.add(getRightCenterPane(),BorderLayout.CENTER);
    	}
    	
    	return centerPane;
    }
    
    protected JPanel getLeftCenterPane(){
    	if(leftCenterPane == null){
    		leftCenterPane = new JPanel();
    		leftCenterPane.setBackground(Color.WHITE);
    		leftCenterPaneGridbag = new GridBagLayout();
    		leftCenterPaneConstraints = new GridBagConstraints();
			leftCenterPane.setLayout(leftCenterPaneGridbag);
			
			//titleStepLabel
			leftCenterPaneConstraints.fill = GridBagConstraints.BOTH;
			leftCenterPaneConstraints.weightx=0.0;
			leftCenterPaneConstraints.weighty=0.0;	
			leftCenterPaneConstraints.anchor=GridBagConstraints.ABOVE_BASELINE_LEADING;
			leftCenterPaneConstraints.insets = new Insets(5,5,0,5);
			leftCenterPaneConstraints.gridx = 0;
			leftCenterPaneConstraints.gridy = 0;
			leftCenterPaneConstraints.gridwidth = 1;
			leftCenterPaneConstraints.gridheight = 1;
    		
    		titleStepLabel = new JLabel(LanguageLoader.getString("Step"));
    		Font font = titleStepLabel.getFont();
    		font.deriveFont(Font.ITALIC);
    		titleStepLabel.setFont(font);
    		leftCenterPane.add(titleStepLabel,leftCenterPaneConstraints);
    		
    		leftCenterPaneConstraints.gridy = GridBagConstraints.RELATIVE;
    		leftCenterPaneConstraints.insets = new Insets(0,5,5,5);
    		leftCenterPane.add(new JSeparator(),leftCenterPaneConstraints);
    		leftCenterPaneConstraints.insets = new Insets(5,5,5,5);
    	}
    	return leftCenterPane;
    }

    
    protected JPanel getRightCenterPane(){
    	if(rightCenterPane == null){
    		rightCenterPane = new JPanel();
    		cardLayout = new CardLayout();
    		rightCenterPane.setLayout(cardLayout);
    	}
    	return rightCenterPane;
    }
    
    public void addPage(IWizardPage page){
    	getRightCenterPane().add((Component) page, page.getPageName());
    	
    	JLabel setpLabel = new JLabel(getPageCount()+": " + page.getPageName());
    	if(setpLabels == null){
    		setpLabels = new Vector<JLabel>();
    	}
		setpLabels.add(setpLabel);
		getLeftCenterPane().add(setpLabel, leftCenterPaneConstraints);
    }
    
    protected void finishAddPage(){
		//spaceLabelBottom
    	leftCenterPaneConstraints.weighty=1.0;
		getLeftCenterPane().add(new JLabel(), leftCenterPaneConstraints);
		leftCenterPaneConstraints.weighty = 0.0;
		
		//leftCenterPane's width.
		 getLeftCenterPane().setPreferredSize(getLeftCenterPane().getPreferredSize());

		
		//set canFinishPageCount
		if(canFinishPageCount == -1){ 
			//if not set canFinishPageCount. Set the maxPageCount can finish.
			canFinishPageCount = getPageCount();
		}
		
		//
		showFirst();
    }
    
	/**
	 * @return the visible card and update the current Card index.
	 * */
	protected IWizardPage findCurrentPage() {
		JPanel visibleComp = null;

		synchronized (getRightCenterPane().getTreeLock()) {
			int ncomponents = getRightCenterPane().getComponentCount();
			for (int i = 0; i < ncomponents; i++) {
				Component comp = getRightCenterPane().getComponent(i);
				if(comp instanceof JPanel){
					if (comp.isVisible()) {
						visibleComp = (JPanel) comp;
						currentPageIndex = i;
						break;
					}
				}

			}
		}
		currentPage = visibleComp;
		return (IWizardPage) currentPage;
	}
	
	/**
	 * @return currentPage.
	 * */
	public IWizardPage getCurrentPage(){
		return findCurrentPage();
	}
	public int getCurrentPageIndex(){
		 findCurrentPage();
		 return currentPageIndex;
	}
    public JButton getBackButton(){
    	if(backButton == null){
    		backButton = new JButton(LanguageLoader.getString("Back"));
    		backButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent event) {
					backButtonActionPerformed(event);
				}
			});
    	}
    	return backButton;
    }
    
    public JButton getNextButton(){
    	if(nextButton == null){
    		nextButton = new JButton(LanguageLoader.getString("Next"));
    		nextButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent event) {
					nextButtonActionPerformed(event);
				}
			});
    	}
    	return nextButton;
    }
    public void backButtonActionPerformed(ActionEvent event)
    {
    	showPrevious();
    }
    public void nextButtonActionPerformed(ActionEvent event)
    {
    	showNext();
    }
    
    public void showFirst(){
    	//layout the LeftCenterPane.
    	
    	cardLayout.first(getRightCenterPane());
    	updateCurrentState();
    }
    public void showPrevious(){
    	cardLayout.previous(getRightCenterPane());
    	updateCurrentState();
    }
    public void showNext(){
    	//check currentPage data.
    	if(checkData()){
    		//processData
    		processData();
        	cardLayout.next(getRightCenterPane());
        	updateCurrentState();
    	}
    }
    protected void showLast(){
    	cardLayout.last(getRightCenterPane());
    	updateCurrentState();
    }
    private boolean isFirst(){
    	return currentPageIndex == 0;
    }
    private boolean isLast(){
    	return currentPageIndex == getPageCount()-1;
    }
    
	protected boolean checkData() {
		// TODO Auto-generated method stub
		errorMessage = "";

		IWizardPage page = getCurrentPage();
		if (page == null) {
			return false;
		}

		errorMessage = page.checkData();

		errorMessage = errorMessage == null ? "" : errorMessage;
		this.setMessageLabel(errorMessage);

		return errorMessage.trim().equals("") ? true : false;
	}

	protected void processData() {
		// TODO Auto-generated method stub
		getCurrentPage().processData(entity);

	}
	
    private synchronized void updateCurrentState(){
    	findCurrentPage();
    	
    	if(currentPage == null){
    		logger.debug("Wizard: CurrentPage is null.");
    		return;
    	}
    	//
    	if(isFirst()){
    		getBackButton().setEnabled(false);
    	}
    	else{
    		getBackButton().setEnabled(true);
    	}
    	//
    	if(isLast()){
    		getNextButton().setEnabled(false);
    	}
    	else{
    		getNextButton().setEnabled(true);
    	}
    	
    	//set finishButton state.
    	logger.debug("canFinishPageIndex=" + canFinishPageCount + "  currentPageIndex=" + currentPageIndex);
    	if(currentPageIndex >= canFinishPageCount - 1){
    		getFinishButton().setEnabled(true);
    	}
    	else{
    		getFinishButton().setEnabled(false);
    	}
    	
    	int size = setpLabels.size();

    	for(int i = 0; i < size; i++){
    		JLabel label = setpLabels.elementAt(i);
    	   //Notice: label.getText() = getCount() + ":" + currentPage.getName()
    		if(label.getText().split(":")[1].trim().equals(currentPage.getName())){
    			label.setBorder(BorderFactory.createLineBorder(Color.RED));
    		}
    		else{
    			label.setBorder(BorderFactory.createEmptyBorder());	
    		}
    	} 	
    }
    
	/**
	 * @return the dataEntity
	 */
	public Entity getEntity() {
		return entity;
	}
	/**
	 * @param dataEntity the dataEntity to set
	 */
	public void setEntity(Entity entity) {
		this.entity = entity;
	}
}
